import { MenuItem } from '@/api/userCenter/system/model/menuModel'
import {
  AddRoleReq,
  EditRoleReq,
  RoleItem,
  UpdateRolePermReq,
} from '@/api/userCenter/authority/model/roleModel'
import {
  deleteRole,
  insertRole,
  modifyRole,
  queryRolePerm,
  RolesApi,
  updateRolePerm,
} from '@/api/userCenter/authority/roles'
import { useStore } from '@/store'
import { message } from 'ant-design-vue'
import { cloneDeep } from 'lodash-es'
import { computed, reactive, watchEffect } from 'vue'
import { DrawerFormData, DrawerState, TreeCheckEvent } from '../types'
import { getFlatMenuList } from '@/utils/routeHelper'

const useDrawerState = (searchApi: () => Promise<void>) => {
  const store = useStore()
  const initDrawerForm: DrawerFormData = {
    name: '',
    code: '',
    note: '',
    permId: '',
    permName: '',
  }
  const drawerState = reactive<DrawerState>({
    visiable: false,
    title: '新增角色',
    type: 'add',
    formData: cloneDeep(initDrawerForm),
    formRules: {
      name: [
        {
          required: true,
          message: '请输入角色名称',
          trigger: 'blur',
        },
      ],
      code: [
        {
          required: true,
          message: '请输入角色标识',
          trigger: 'blur',
        },
      ],
    },
    labelCol: { span: 4 },
    wrapperCol: { span: 18 },
    treeCheckedKeys: { checked: [], halfChecked: [] },
    treeExpandedKeys: [],
    treeData: [],
    allPermData: [],
    treeFlatData: {},
    treeReplaceFields: { title: 'name', key: 'id' },
    currentApp: '',
    selectAppDisable: false,
  })

  /**
   * 拿到当前用户所有权限列表
   * 拍平权限树，以方便自定义权限树选中和取消选中逻辑
   */
  const getAllPerm = () => {
    const permData = cloneDeep(store.state.account.currentUser?.perms || [])
    drawerState.currentApp = permData[0].id
    drawerState.allPermData = permData
    drawerState.treeData = [permData[0]]
    drawerState.treeFlatData = getFlatMenuList(permData)
  }
  watchEffect(() => {
    const expandIds: string[] = []
    drawerState.treeData = drawerState.allPermData.filter(
      (item) => item.id === drawerState.currentApp
    )
    // 默认展开第一层和第二层树
    drawerState.treeData.forEach((item) => {
      expandIds.push(item.id)
      if (item.children) {
        item.children.forEach((citem) => {
          expandIds.push(citem.id)
        })
      }
    })
    drawerState.treeExpandedKeys = expandIds
  })

  /**
   * 弹框关闭事件
   */
  const onDrawerClose = () => {
    drawerState.visiable = false
    drawerState.formData = cloneDeep(initDrawerForm)
    drawerState.treeCheckedKeys = { checked: [], halfChecked: [] }
    drawerState.selectAppDisable = false
  }

  /**
   * 打开新增弹框
   */
  const openAddDrawer = async () => {
    drawerState.type = 'add'
    drawerState.title = '新增角色'
    drawerState.visiable = true
  }

  /**
   * 打开编辑弹框
   */
  const openEditDrawer = async (record: RoleItem) => {
    drawerState.selectAppDisable = true
    const { data } = await queryRolePerm(record.id)
    drawerState.treeCheckedKeys = { checked: data, halfChecked: [] }
    drawerState.type = 'edit'
    drawerState.title = '编辑角色'
    drawerState.formData = cloneDeep(record)
    drawerState.currentApp = record.permId
    drawerState.visiable = true
  }
  const queryRolePermLoading = computed(() =>
    store.getters['global/isOpLoading'](RolesApi.QUERY_ROLE_PERM)
  )

  /**
   * 确认弹框修改/添加内容
   */
  const onEnterDrawer = async () => {
    if (drawerState.type === 'add') {
      drawerState.formData.permId = drawerState.currentApp
      const editRoleReqData: AddRoleReq = drawerState.formData
      const { data } = await insertRole(editRoleReqData)
      const updatePermReqData: UpdateRolePermReq = {
        id: data.id,
        permIds: drawerState.treeCheckedKeys.checked,
      }
      await updateRolePerm(updatePermReqData)
      message.success('新增成功！')
    } else if (drawerState.type === 'edit') {
      const editRoleReqData: EditRoleReq = drawerState.formData as EditRoleReq
      const updatePermReqData: UpdateRolePermReq = {
        id: editRoleReqData.id,
        permIds: drawerState.treeCheckedKeys.checked,
      }
      await modifyRole(editRoleReqData)
      await updateRolePerm(updatePermReqData)
      message.success('修改成功！')
    }
    await searchApi()
    drawerState.visiable = false
  }
  const insertRoleLoading = computed(() =>
    store.getters['global/isOpLoading'](RolesApi.INSERT_ROLE)
  )
  const updateRolePermLoading = computed(() =>
    store.getters['global/isOpLoading'](RolesApi.UPDATE_ROLE_PERM)
  )
  const modifyRoleLoading = computed(() =>
    store.getters['global/isOpLoading'](RolesApi.EDIT_ROLE)
  )

  /**
   * 删除角色
   */
  const delRole = async (record: RoleItem) => {
    const reqData = { ids: [record.id] }
    await deleteRole(reqData)
    message.success('删除成功！')
    await searchApi()
  }
  const deleteRoleLoading = computed(() =>
    store.getters['global/isOpLoading'](RolesApi.DELETE_ROLE)
  )

  /**
   * 批量删除角色
   */
  const delManyRole = async (ids: string[]) => {
    const reqData = { ids }
    await deleteRole(reqData)
    message.success('删除成功！')
    await searchApi()
  }

  /**
   * 自定义权限树选中逻辑
   */
  const onTreeCheck = (_: string[], event: TreeCheckEvent) => {
    const { checkedNodes } = event
    if (event.checked) {
      // 如果是选中
      // 要顺便把当前选中节点的所有父节点选中
      checkedNodes.forEach((nodes) => {
        const nodeProps: MenuItem = nodes.props
        getPids(nodeProps.pid)
      })
    } else {
      // 如果是取消选中
      // 要顺便把当前取消选中的节点的所有子节点取消选中
      const children = event.node.dataRef.children
      if (children && children.length > 0) {
        getChildren(children)
      }
    }
  }

  /**
   * 获取指定菜单项的所有父节点
   */
  const getPids = (pid: string) => {
    const pNode = drawerState.treeFlatData[pid]
    if (pNode && !drawerState.treeCheckedKeys.checked.includes(pNode.id)) {
      drawerState.treeCheckedKeys.checked.push(pNode.id)
      if (pNode.pid !== '0') {
        getPids(pNode.pid)
      }
    }
  }

  /**
   * 获取指定菜单项的所有子节点
   */
  const getChildren = (chidren: MenuItem[]) => {
    const chidrenFlat = getFlatMenuList(chidren)
    Object.keys(chidrenFlat).forEach((id) => {
      const indexPos = drawerState.treeCheckedKeys.checked.indexOf(id)
      if (indexPos !== -1) {
        drawerState.treeCheckedKeys.checked.splice(indexPos, 1)
      }
    })
  }

  return {
    openAddDrawer,
    onDrawerClose,
    openEditDrawer,
    drawerState,
    onEnterDrawer,
    insertRoleLoading,
    delRole,
    deleteRoleLoading,
    modifyRoleLoading,
    delManyRole,
    getAllPerm,
    onTreeCheck,
    updateRolePermLoading,
    queryRolePermLoading,
  }
}

export default useDrawerState
